<?php
/**
 * 关联Map类
 * 
 * 既可以使用对象的方法，又可以使用[]（一对方括号）访问元素
 * <code>
 * <?php
 * $map = new IAssocMap(array(1=>"a", 2=>"b", 3=>"c", 4=>"d", 5=>"f"));
 * echo $map[2] . "\n"; // =>b
 * echo count($map) . "\n"; // => 5
 * echo isset($map[2]) . "\n"; // => 1
 * unset($map[2]); // unset
 * foreach ($map as $v) { // => a c d f
 * 	echo $v . "\n";
 * }
 * ?>
 *</code>
 * 
 * @version $Id: IAssocMap.php 312 2008-04-23 16:29:38Z iwind $
 * @package util.collection
 * @since 0.0.2
 */
class IAssocMap extends IAbstractCollection implements ArrayAccess,Countable {
	private $array;
	
	/**
	 * 构造器
	 *
	 * 可以使用如下方法构造：
	 * <code>
	 * <?php
	 * new IAssocMap();
	 * new IAssocMap(array(1=>"a", 2=>"b", 3=>"c"));
	 * new IAssocMap("a"); // 参数无效
	 * ?>
	 * </code>
	 * 
	 * @param array $array 关联数组
	 */
	public function __construct($array = null) {
		if (is_array($array)) {
			$this->array = $array;
		}
		else {
			$this->array = array();
		}
	}
	
	/**
	 * 取得迭代器
	 * 
	 * 实现了 IIterable 接口对应方法
	 *
	 * @return IMapIterator
	 */	
	public function getIterator() {
		return new IMapIterator($this->array);
	}
	
	/**
	 * 计算元素个数
	 * 
	 * 实现了 Countable 接口对应方法
	 *
	 * @return integer
	 */	
	public function count() {
		return count($this->array);
	}
	
	/**
	 * 判断一个键是否存在
	 *
	 * 实现了 ArrayAccess 接口对应方法
	 * 
	 * @param mixed $key 键
	 * @return boolean
	 */	
	public function offsetExists($key) {
		return array_key_exists($key, $this->array);
	}
	
	/**
	 * 取得一个键对应的值
	 * 
	 * 实现了 ArrayAccess 接口对应方法
	 *
	 * @param mixed $key 键
	 * @return mixed 值
	 */
	public function offsetGet($key) {
		if ($this->offsetExists($key)) {
			return $this->array[$key];
		}
		throw new ICollectionException("invalid key '{$key}' for the map");
	}
	
	/**
	 * 设置一个键对应的值
	 * 
	 * 实现了 ArrayAccess 接口对应方法
	 *
	 * @param mixed $key 键
	 * @param mixed $item 值
	 */
	public function offsetSet($key, $item) {
		$this->array[$key] = $item;
	}
	
	/**
	 * 销毁一个键对应的元素
	 * 
	 * 实现了 ArrayAccess 接口对应方法
	 *
	 * @param mixed $key 键
	 */
	public function offsetUnset($key) {
		if ($this->offsetExists($key)) {
			unset($this->array[$key]);
		}
	}
	
	/**
	 * 加入新的元素
	 *
	 * @param mixed $key 键
	 * @param mixed $value 值
	 */
	public function put($key, $value) {
		$this->offsetSet($key, $value);
	}
	
	/**
	 * 将map转换成数组
	 * 
	 * 实现了 IIterable 对应的方法
	 *
	 * @return array
	 */
	public function toArray() {
		return $this->array;
	}
	
	/**
	 * 取得键对应的值
	 * 
	 * 如果没有找到该键，则返回null
	 *
	 * @param mixed $key 键
	 * @return mixed
	 */
	public function get($key) {
		if ($this->offsetExists($key)) {
			return $this->offsetGet($key);
		}
		return null;
	}
	
	/**
	 * 计算map的元素数目
	 *
	 * @return integer
	 */
	public function size() {
		return $this->count();
	}
	
	/**
	 * 删除键对应的元素
	 *
	 * @param mixed $key 键
	 */
	public function remove($key) {
		$this->offsetUnset($key);
	}
	
	/**
	 * 从另一个iterable中加入新的元素
	 *
	 * @param mixed $iterable array/IIterable
	 */
	public function putAll($iterable) {
		if (is_array($iterable) || ($iterable instanceof IIterable)) {
			foreach ($iterable as $key=>$value) {
				$this->offsetSet($key, $value);
			}
		}
	}
	
	/**
	 * 判断当前map是否为空
	 *
	 * @return boolean
	 */
	public function isEmpty() {
		return empty($this->array);
	}
	
	/**
	 * 判断当前map是否包含某个键
	 *
	 * @param mixed $key 键
	 * @return boolean
	 */
	public function containsKey($key) {
		return $this->offsetExists($key);
	}
	
	/**
	 * 取得当前map中键的列表
	 *
	 * @return IArrayList
	 */
	public function keys() {
		return new IArrayList(array_keys($this->array));
	}
	
	/**
	 * 取得当前map中值的列表
	 *
	 * @return IArrayList
	 */
	public function values() {
		return new IArrayList(array_values($this->array));
	}
	
	/**
	 * 判断当前map是否包含值
	 *
	 * @param mixed $value 值
	 * @return boolean
	 */
	public function containsValue($value) {
		return in_array($value, $this->array);
	}
	
	/**
	 * 清空map
	 *
	 */
	public function clear() {
		$this->array = array();
	}
}

?>